package com.zmn.oms.third.koubei.service.impl;

import com.alibaba.fastjson.JSON;
import com.qimencloud.api.sceneqimen.request.TaobaoLifeReservationItemDateInventoryQueryRequest;
import com.qimencloud.api.sceneqimen.request.TaobaoLifeReservationOrderDoorCreateRequest;
import com.taobao.api.ApiException;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
import com.taobao.api.TaobaoResponse;
import com.taobao.api.request.LifeReservationItemOrderChangeRequest;
import com.taobao.api.response.LifeReservationItemOrderChangeResponse;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.channel.product.third.ChannelProductThirdListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.consts.GlobalDict;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.baidumap.BaiduMapBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderDutyConsts;
import com.zmn.oms.common.constant.RedisKeyConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.order.OrderBO;
import com.zmn.oms.model.dto.baidumap.LngLatLocation;
import com.zmn.oms.model.dto.order.proxy.CreateOrderDTO;
import com.zmn.oms.model.dto.product.OrderProductDTO;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkLogChange;
import com.zmn.oms.model.vo.work.ZsOrderWorkVO;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.koubei.KoubeiChannelEnum;
import com.zmn.oms.third.koubei.KoubeiConsts;
import com.zmn.oms.third.koubei.dto.KoubeiCreateOrderResponse;
import com.zmn.oms.third.koubei.dto.KoubeiOrderCreateRequest;
import com.zmn.oms.third.koubei.dto.KoubeiQueryInventoryResponse;
import com.zmn.oms.third.koubei.service.KoubeiService;
import com.zmn.oms.zmn.business.interfaces.proxy.ProxyOrderBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkQueryBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import com.zmn.pay.common.constant.PayConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by ThinkPad on 2021/8/16.
 */
@Slf4j
@Service("koubeiService")
public class KoubeiServiceImpl implements KoubeiService {

    @Autowired
    private OrderWorkService orderWorkService;

    @Autowired
    private OrderExtendService orderExtendService;

    @Autowired
    private ProxyOrderBService proxyOrderBService;

    @Autowired
    private ZsOrderWorkQueryBService zsOrderWorkQueryBService;

    @Autowired
    private WorkFlowContextBService workFlowContextBService;

    @Autowired
    private BaiduMapBService baiduMapBService;

    @Autowired
    private RedisManager redisManager;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private AreaListRemoteService areaListRemoteService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ChannelProductThirdListRemoteService channelProductThirdListRemoteService;

    /**
     * 领单同步
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderTake(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 订单履约状态同步，领单 - 已准备
        this.syncOrderStatus(orderWorkLogChange.getOrderId() ,orderWorkLogChange.getWorkId(),
                KoubeiConsts.SYNC_ACTION_PUSH, KoubeiConsts.SYNC_STATUS_PREPARED);
    }

    /**
     * 改约同步
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderDutytime(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 工单查询
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(),orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("查找对应的订单失败");
        }

        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getWorkId());
        if (Objects.isNull(orderExtend)) {
            throw new OmsBaseException("查找订单扩展数据失败");
        }

        // 预约状态
        if (Objects.equals(OrderDutyConsts.DUTY_STATUS_FAIL, orderWork.getDutyStatus()) ||
                Objects.equals(OrderDutyConsts.DUTY_STATUS_SUSPEND, orderWork.getDutyStatus())) {
            throw new OmsBaseException("预约状态不为预约成功，不同步");
        }

        // 预约失败
        Date dutyTime = orderWork.getDutyTime();
        if (Objects.isNull(dutyTime)) {
            throw new OmsBaseException("预约时间为空，不同步");
        }

        String reserveTimeDay = DateUtil.toString(dutyTime,"yyyy-MM-dd");

        // 生成请求数据
        LifeReservationItemOrderChangeRequest orderChangeRequest = new LifeReservationItemOrderChangeRequest();
        orderChangeRequest.setTradeNo(orderWork.getOuterId());
        orderChangeRequest.setReservationOrderId(orderExtend.getExtOuterId());
        orderChangeRequest.setAction(KoubeiConsts.SYNC_ACTION_MODIFY);
        orderChangeRequest.setReserveStartTime(String.format("%s 00:00", reserveTimeDay));
        orderChangeRequest.setReserveEndTime(String.format("%s 23:59", reserveTimeDay));

        // 发送请求
        this.sendTaobaoOrderChangeRequest(orderChangeRequest);
    }

    /**
     * 上门同步
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderVisit(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 订单履约状态同步，上门 - 处理中
        this.syncOrderStatus(orderWorkLogChange.getOrderId() ,orderWorkLogChange.getWorkId(),
                KoubeiConsts.SYNC_ACTION_PUSH, KoubeiConsts.SYNC_STATUS_PROCESSING);
    }

    /**
     * 取消同步
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderCancel(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 订单履约状态同步，取消
        this.syncOrderStatus(orderWorkLogChange.getOrderId() ,orderWorkLogChange.getWorkId(),
                KoubeiConsts.SYNC_ACTION_CANCEL, "");
    }

    /**
     * 完成同步
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderComplete(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 订单履约状态同步，完成 - 服务完毕
        this.syncOrderStatus(orderWorkLogChange.getOrderId() ,orderWorkLogChange.getWorkId(),
                KoubeiConsts.SYNC_ACTION_PUSH, KoubeiConsts.SYNC_STATUS_PROCESSED);
    }

    /**
     * 处理预约库存查询
     * @param requestBody
     * @return
     * @throws Exception
     */
    @Override
    public KoubeiQueryInventoryResponse handleInventoryQueryRequest(String requestBody) throws OmsBaseException {

        TaobaoLifeReservationItemDateInventoryQueryRequest queryRequest;
        try {
            queryRequest = JSON.parseObject(requestBody,TaobaoLifeReservationItemDateInventoryQueryRequest.class);
        } catch (Exception e) {
            throw new OmsBaseException("请求内容解析失败");
        }

        log.info("【{}】 查询预约时间库存，request id：[{}]，淘宝商品id：[{}]，口碑门店id：[{}]，淘宝门店id：[{}], 区域：[{}]，详细地址：[{}]",
                KoubeiConsts.CHANNEL_NAME, queryRequest.getRequestId(), queryRequest.getTbItemId(), queryRequest.getShopId(),
                queryRequest.getStoreId(),queryRequest.getDistrict(),queryRequest.getDetailAddress());

        // 结果：15天内的早8点到晚8点，库存量固定为200，当天根据查询时间判断
        KoubeiQueryInventoryResponse queryResponse = new KoubeiQueryInventoryResponse();
        queryResponse.setErrorMessage("OK");

        Date curDate = DateUtil.getNow();
        List<KoubeiQueryInventoryResponse.DateInventory> dateInventoryList = new ArrayList<>(KoubeiConsts.INVENTORY_MAX_DAY);
        for (int index = 0 ;index < KoubeiConsts.INVENTORY_MAX_DAY; index ++ ) {
            KoubeiQueryInventoryResponse.DateInventory dateInventory = queryResponse.new DateInventory();

            boolean curDay = index == 0 ? true : false;
            if (curDay) {
                dateInventory.setDate(DateUtil.toString(curDate, DateUtil.FORMAT_DATE));
            } else {
                dateInventory.setDate(DateUtil.toString(DateUtil.addDays(curDate,index), DateUtil.FORMAT_DATE));
            }

            List<KoubeiQueryInventoryResponse.TimeUnit> timeUnits = new ArrayList<>(KoubeiConsts.INVENTORY_TIME_SECTION_NUMBER);

            int beginHour = KoubeiConsts.INVENTORY_HOUR_START;
            for (int ts = 0; ts < KoubeiConsts.INVENTORY_TIME_SECTION_NUMBER ; ts ++) {

                if (curDay && DateUtil.getHour(curDate) >= (beginHour + 1)) {
                    beginHour += 2;
                    continue;
                }

                KoubeiQueryInventoryResponse.TimeUnit timeUnit = queryResponse.new TimeUnit();
                timeUnit.setCount(KoubeiConsts.INVENTORY_NUMBER);
                timeUnit.setStatus(KoubeiConsts.INVENTORY_STATUS_OPEN);
                timeUnit.setStartTime(String.format("%02d:00",beginHour));
                timeUnit.setEndTime(String.format("%02d:00",beginHour + 2));

                timeUnits.add(timeUnit);
                beginHour += 2;
            }

            dateInventory.setTimeUnits(timeUnits);
            dateInventoryList.add(dateInventory);
        }

        queryResponse.setDateInventoryList(dateInventoryList);

        return queryResponse;
    }

    /**
     * 处理订单创建
     * @param requestBody
     * @return
     * @throws Exception
     */
    @Override
    public KoubeiCreateOrderResponse handleCreateOrderRequest(String requestBody) throws OmsBaseException {

        // 解析消息
        KoubeiOrderCreateRequest createRequest;
        try {
            createRequest = JSON.parseObject(requestBody,KoubeiOrderCreateRequest.class);
        } catch (Exception e) {
            throw new OmsBaseException("请求内容解析失败");
        }

        // 创建订单
        Long orderId;
        try {
            orderId = this.doCreateOrder(createRequest);
        } catch (OmsBaseException oe) {

            log.info("【{}】保存订单异常，OmsBaseException【{}】 ", KoubeiConsts.CHANNEL_NAME,oe.getMessage());
            this.setRedisClueData(createRequest.getTradeNo(),GlobalConsts.NO);
            throw oe;
        } catch (Exception e) {

            log.info("【{}】保存订单异常，Exception【{}】 ", KoubeiConsts.CHANNEL_NAME,e.getMessage());
            this.setRedisClueData(createRequest.getTradeNo(),GlobalConsts.NO);
            throw new OmsBaseException(e.getMessage());
        }

        this.setRedisClueData(createRequest.getTradeNo(),GlobalConsts.NONE);

        // 应答消息
        KoubeiCreateOrderResponse createResponse = new KoubeiCreateOrderResponse(String.valueOf(orderId));
        createResponse.setErrorMessage("OK");

        return createResponse;
    }

    /**
     * 创建订单
     * @param createRequest
     * @return
     * @throws OmsBaseException
     */
    private Long doCreateOrder(KoubeiOrderCreateRequest createRequest) throws OmsBaseException {

        // 数据去重
        Long orderId = this.verifyOrderCreateRequest(createRequest);
        if (NumberUtil.isNotNullOrZero(orderId)) {
            return orderId;
        }

        log.info("【{}】预约订单创建，request id：[{}]，淘宝商品id：[{}]，淘宝主单号：[{}]，预约主单id：[{}]",
                KoubeiConsts.CHANNEL_NAME, createRequest.getRequestId(), createRequest.getTbItemId(), createRequest.getTradeNo(),
                createRequest.getReservationOrderId());

        // 生成创建订单的数据
        CreateOrderDTO createOrderDTO = buildCreateOrderDTO(createRequest);

        // 创建订单
        OrderBO orderBO = proxyOrderBService.createOrder(createOrderDTO);
        OrderWork orderWork = orderBO.getOrderWork();

        log.info("【{}】保存订单成功 OrderId:[{}]", KoubeiConsts.CHANNEL_NAME, orderWork.getOrderId());

        // 工单自动流转
        workFlowContextBService.asyncAutoFlow(orderWork.getOrderId(),orderWork.getWorkId());

        return orderWork.getOrderId();
    }

    /**
     * 生成创建订单的数据
     * @param createRequest
     * @return
     * @throws OmsBaseException
     */
    private CreateOrderDTO buildCreateOrderDTO(KoubeiOrderCreateRequest createRequest) throws OmsBaseException {

        // 数据判断
        if (Objects.isNull(createRequest)) {
            throw new OmsBaseException("请求数据为空");
        }

        if (StringUtil.isBlank(createRequest.getTradeNo()) || StringUtil.isBlank(createRequest.getReservationOrderId())) {
            throw new OmsBaseException("Tp主单号/预约主单号为空");
        }

        if (StringUtil.isBlank(createRequest.getAddressList())) {
            throw new OmsBaseException("预约地址列表字段为空");
        }

        // 预约地址列表
        List<TaobaoLifeReservationOrderDoorCreateRequest.ReservationAddress> addressList = JSON.parseArray(createRequest.getAddressList(),
                TaobaoLifeReservationOrderDoorCreateRequest.ReservationAddress.class);
        if (CollectionUtil.isNullOrEmpty(addressList)) {
            throw new OmsBaseException("预约地址列表为空");
        }

        // 预约地址
        TaobaoLifeReservationOrderDoorCreateRequest.ReservationAddress reservationAddress = addressList.get(0);

        // 订单电话，预约，地址，备注读取
        String telephone = null;
        String dutyTime = null;
        String address = null;
        String remark = null;
        Long productCount = 1L;
        Integer prepayMoney = KoubeiConsts.PREPAY_MONEY;

        address = Optional.ofNullable(reservationAddress.getDistrict()).orElse("") +
                Optional.ofNullable(reservationAddress.getDetailAddress()).orElse("");
        telephone = Optional.ofNullable(reservationAddress.getContactPhone()).orElse("");


        // 预约详情
        if (StringUtil.isNotBlank(createRequest.getReservationDetail())) {

            TaobaoLifeReservationOrderDoorCreateRequest.ReservationDetail reservationDetail = JSON.parseObject(createRequest.getReservationDetail(),
                    TaobaoLifeReservationOrderDoorCreateRequest.ReservationDetail.class);

            remark = Optional.ofNullable(reservationDetail).map(rd -> rd.getMemo()).orElse("");
            productCount = Optional.ofNullable(reservationDetail).map(rd -> rd.getItemCount()).orElse(1L);

            String realAmount = Optional.ofNullable(reservationDetail).map(rd ->rd.getSingleRealAmount()).orElse("");
            if (StringUtil.isNotBlank(realAmount)) {
                prepayMoney = NumberUtil.convertMoneyToFen(realAmount) * productCount.intValue();
            }

            if (StringUtil.isBlank(telephone)) {
                telephone = Optional.ofNullable(reservationDetail).map(rd -> rd.getContactPhone()).orElse("");
            }
        }

        if (StringUtil.isBlank(telephone)) {
            throw new OmsBaseException("客户电话为空");
        }

        // 预约时间
        if (StringUtil.isNotBlank(createRequest.getReserveTimeList())) {
            List<TaobaoLifeReservationOrderDoorCreateRequest.ReservationTime> reservationTimeList = JSON.parseArray(createRequest.getReserveTimeList(),
                    TaobaoLifeReservationOrderDoorCreateRequest.ReservationTime.class);
            if (CollectionUtil.isNotNullOrEmpty(reservationTimeList)) {

                TaobaoLifeReservationOrderDoorCreateRequest.ReservationTime reservationTime = reservationTimeList.get(0);
                dutyTime = Optional.ofNullable(reservationTime.getStartTime()).orElse(reservationTime.getEndTime());
            }
        }

        // 订单创建数据
        CreateOrderDTO createOrderDTO = new CreateOrderDTO();

        // 输入类型
        createOrderDTO.setInputType(OrderConsts.ORDER_INPUT_TYPE_API);

        // 渠道id
        createOrderDTO.setChannelId(this.getChannelId(createRequest));

        // 外部订单id - Tp主单号
        createOrderDTO.setOuterId(createRequest.getTradeNo());

        // 联系人
        createOrderDTO.setContactName(reservationAddress.getContactName());

        // 联系人电话
        createOrderDTO.setTelephone(telephone);

        // 性别
        createOrderDTO.setGender(GlobalDict.GENDER_NO);

        // 预约时间
        if (StringUtil.isNotBlank(dutyTime)) {
            createOrderDTO.setDutyTime(DateUtil.parse(dutyTime, DateUtil.FORMAT_DATETIME));
        }

        // 地址
        createOrderDTO.setAddress(reservationAddress.getDetailAddress());

        // 厂商单
        createOrderDTO.setFactory(GlobalConsts.NO);

        // 备注
        createOrderDTO.setRemark(remark);

        // 业务类型
        createOrderDTO.setBizType(GlobalConsts.BIZ_TYPE_C);

        // 平台
        createOrderDTO.setPlat(GlobalConsts.PLAT_MARK_ZMN);

        // 禁止弃单
        createOrderDTO.setDisableDiscard(GlobalConsts.NO);

        // 操作人
        createOrderDTO.setOperator("系统");

        // 操作人id
        createOrderDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);

        // 操作者类型
        createOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);

        // 预付
        createOrderDTO.setChannelPrepayAmount(0);

        // 城市id
        this.handleCreateOrderAddress(address, createOrderDTO);

        // 产品
        this.handleCreateOrderProduct(createRequest.getTbItemId(), productCount.intValue(), createOrderDTO);

        // 第三方店铺 ID
        createOrderDTO.setExternalShopId(createRequest.getShopId());

        // 预付
        if (prepayMoney > 0) {
            createOrderDTO.setChannelPrepayAmount(prepayMoney);
            createOrderDTO.setChannelPrepayStatus(PayConsts.PAY_STATUS_DONE);
        }

        // 日志记录
        StringBuilder sbOperateLog = new StringBuilder();
        sbOperateLog.append("<br/> 淘宝商品id：").append(createRequest.getTbItemId()).
                append("<br/> Tp主单号：").append(createRequest.getTradeNo()).
                append("<br/> 预约主单ID：").append(createRequest.getReservationOrderId()).
                append("<br/>");

        createOrderDTO.setOperatorLogRemark(sbOperateLog.toString());

        // 渠道扩展订单号
        createOrderDTO.setExtOuterId(createRequest.getReservationOrderId());

        return createOrderDTO;
    }

    /**
     * 处理订单的地址信息
     * @param address
     * @param createOrderDTO
     */
    private void handleCreateOrderAddress(String address, CreateOrderDTO createOrderDTO) {

        // 设置默认城市为重庆
        createOrderDTO.setCityId(500100);

        // 详细地址获取经纬度
        LngLatLocation areaLocation = baiduMapBService.location(address);
        if (Objects.isNull(areaLocation)) {
            log.info("【{}】地址信息解析失败",KoubeiConsts.CHANNEL_NAME);
            return;
        }

        // 设置经纬度
        createOrderDTO.setLatitude(Double.valueOf(areaLocation.getLat()));
        createOrderDTO.setLongitude(Double.valueOf(areaLocation.getLng()));

        // 经纬度查找区域信息
        ResponseDTO<AreaDRO> areaResponse = areaListRemoteService.getAreaByLatAndLng(Double.valueOf(areaLocation.getLng()), Double.valueOf(areaLocation.getLat()));
        if (Objects.isNull(areaResponse) || Objects.isNull(areaResponse.getData())) {
            log.info("【{}】根据经纬度查找地址信息失败", KoubeiConsts.CHANNEL_NAME);
            return;
        }

        createOrderDTO.setCityId(areaResponse.getData().getParentId());

        // 再设一次经纬度
        Double longitude = Double.valueOf(areaResponse.getData().getLongitude());
        Double latitude = Double.valueOf(areaResponse.getData().getLatitude());
        createOrderDTO.setLongitude(longitude);
        createOrderDTO.setLatitude(latitude);
    }

    /**
     * 创建订单的产品信息
     * @param channelProduct
     * @param productCount
     * @param createOrderDTO
     */
    private void handleCreateOrderProduct(String channelProduct, Integer productCount, CreateOrderDTO createOrderDTO) {

        // 产品列表
        List<OrderProductDTO> orderProductList =  new LinkedList<>();
        OrderProductDTO orderProductDTO = new OrderProductDTO();

        // 查找产品id
        ResponseDTO<List<ProductBaseDRO>> productListResponseDTO = channelProductThirdListRemoteService.listByChannelIdAndProductParentIdAndSubId(createOrderDTO.getChannelId(),
                channelProduct, null);

        if (!productListResponseDTO.isSuccess() || Objects.isNull(productListResponseDTO.getData()) || productListResponseDTO.getData().isEmpty()) {
            orderProductDTO.setProductId(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID);
        } else {

            // 映射为前台产品
            orderProductDTO.setShowProductId(productListResponseDTO.getData().get(0).getProductId());
            orderProductDTO.setProductShowType(GlobalConsts.YES);
        }

        orderProductDTO.setNumber(productCount);
        orderProductList.add(orderProductDTO);
        createOrderDTO.setOrderProductList(orderProductList);
    }

    /**
     * 获取渠道id
     * @param createRequest
     * @return
     */
    private Integer getChannelId(KoubeiOrderCreateRequest createRequest) {

        return KoubeiChannelEnum.getChannelIdByChannelPid(createRequest.getMerchantPid());
    }

    /**
     * 同步订单履约状态
     *
     * @param orderId
     * @param workId
     * @param action
     * @param status
     * @throws OmsBaseException
     */
    private void syncOrderStatus(Long orderId, Long workId, String action, String status) throws OmsBaseException {

        // 参数判断
        if (NumberUtil.isNullOrZero(orderId) || NumberUtil.isNullOrZero(workId)) {
            throw new OmsBaseException("同步订单履约状态订单id为空");
        }

        // 查找订单失败
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId,workId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("查找对应的订单失败");
        }

        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getWorkId());
        if (Objects.isNull(orderExtend)) {
            throw new OmsBaseException("查找订单扩展数据失败");
        }

        // 生成请求数据
        LifeReservationItemOrderChangeRequest orderChangeRequest = new LifeReservationItemOrderChangeRequest();
        orderChangeRequest.setTradeNo(orderWork.getOuterId());
        orderChangeRequest.setReservationOrderId(orderExtend.getExtOuterId());
        orderChangeRequest.setAction(action);
        orderChangeRequest.setTargetFulfillmentStatus(status);

        // 发送请求
        this.sendTaobaoOrderChangeRequest(orderChangeRequest);
    }

    /**
     * 同步请求
     * @param orderChangeRequest
     * @throws Exception
     */
    private void sendTaobaoOrderChangeRequest(LifeReservationItemOrderChangeRequest orderChangeRequest) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(orderChangeRequest)) {
            throw new OmsBaseException("请求数据为空");
        }

        // 生成请求
        TaobaoClient client = new DefaultTaobaoClient(KoubeiConsts.API_URL,KoubeiConsts.APP_KEY,KoubeiConsts.APP_SECRET);
        if (Objects.isNull(client)) {
            throw new OmsBaseException("初始化TaobaoClient失败");
        }

        log.info("【{}】同步订单变更数据，请求数据【{}】", KoubeiConsts.CHANNEL_NAME, JSON.toJSONString(orderChangeRequest));

        TaobaoResponse response;
        try {
            // 发送请求
            response = client.execute(orderChangeRequest);
        } catch(ApiException apiException) {
            log.info("【{}】同步订单变更数据请求异常，【{}】【{}】【{}】【{}】", KoubeiConsts.CHANNEL_NAME,
                    apiException.getErrCode(), apiException.getErrMsg(),
                    apiException.getSubErrCode(), apiException.getSubErrMsg());

            throw new OmsBaseException("请求发送异常");
        }

        log.info("【{}】同步订单变更数据请求发送完成，返回数据【{}】", KoubeiConsts.CHANNEL_NAME, JSON.toJSONString(response));
        if (Objects.isNull(response) || !response.isSuccess()) {

            log.info("【{}】发送同步数据请求失败，【{}】【{}】【{}】【{}】", KoubeiConsts.CHANNEL_NAME,
                    Optional.ofNullable(response).map(res->res.getErrorCode()).orElse(""),
                    Optional.ofNullable(response).map(res->res.getMsg()).orElse(""),
                    Optional.ofNullable(response).map(res->res.getSubCode()).orElse(""),
                    Optional.ofNullable(response).map(res->res.getSubMsg()).orElse(""));

            throw new OmsBaseException(String.format("发送请求返回失败,失败提示消息[%s]",Optional.ofNullable(response).map(res->res.getMsg()).orElse("")));
        }

        if (! (response instanceof LifeReservationItemOrderChangeResponse)) {
            throw new OmsBaseException("同步请求的返回数据格式不正确");
        }

        LifeReservationItemOrderChangeResponse orderChangeResponse = (LifeReservationItemOrderChangeResponse)response;
        LifeReservationItemOrderChangeResponse.Result orderChangeResult = orderChangeResponse.getResult();
        if (Objects.nonNull(orderChangeResult) && orderChangeResult.getSuccess()) {
            return;
        }

        throw new OmsBaseException(String.format("发送请求返回失败,失败提示消息[%s]",
                Optional.ofNullable(orderChangeResult.getError()).map(tribeError -> tribeError.getMessage()).orElse("")));
    }

    /**
     * 对创建订单的数据进行去重等验证
     * @param createRequest
     * @throws OmsBaseException
     */
    private Long verifyOrderCreateRequest(KoubeiOrderCreateRequest createRequest) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(createRequest)) {
            throw new OmsBaseException("数据为空");
        }

        // 外部订单号判断
        String outerId = createRequest.getTradeNo();
        if (StringUtil.isBlank(outerId)) {
            throw new OmsBaseException("淘宝主单号为空");
        }

        // redis缓存判断
        if (this.setRedisClueData(outerId, GlobalConsts.YES) > 1) {

            this.setRedisClueData(createRequest.getTradeNo(), GlobalConsts.NO);
            throw new OmsBaseException("有相同淘宝主单号的数据正在处理");
        }

        // 数据库判断
        ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(outerId,getChannelId(createRequest));

        return Optional.ofNullable(zsOrderWorkVO).map(vo->vo.getOrderId()).orElse(0L);
    }

    /**
     * 读取或设置线索缓存数据
     *
     * @param tradeNo
     * @param op
     * @return
     */
    private Long setRedisClueData(String tradeNo, int op) {

        String redisKey = String.format(RedisKeyConsts.KOUBEI_CLUE_REDIS_KEY, tradeNo);
        Long value = 0L;
        switch (op) {
            case com.zmn.common.constant.GlobalConsts.YES:
                value = redisManager.incr(redisKey);

                // 有效期为5分钟
                redisManager.expire(redisKey,300);
                break;
            case com.zmn.common.constant.GlobalConsts.NO:
                value = redisManager.decr(redisKey);
                break;
            default:
                redisManager.del(redisKey);
        }

        return value;
    }

    public static void main(String[] args) {

        LifeReservationItemOrderChangeRequest orderChangeRequest = new LifeReservationItemOrderChangeRequest();
        orderChangeRequest.setTradeNo("2055779676514211600");
        orderChangeRequest.setReservationOrderId("20210825085882270011500000000016");
        orderChangeRequest.setAction("PUSH_FULFILLMENT");
        orderChangeRequest.setTargetFulfillmentStatus(KoubeiConsts.SYNC_STATUS_PROCESSED);

        TaobaoClient client = new DefaultTaobaoClient(KoubeiConsts.API_URL,KoubeiConsts.APP_KEY,KoubeiConsts.APP_SECRET);
        if (Objects.isNull(client)) {
            log.info("初始化TaobaoClient失败");
            return;
        }

        log.info("【{}】同步订单变更数据，请求数据【{}】", KoubeiConsts.CHANNEL_NAME, JSON.toJSONString(orderChangeRequest));

        TaobaoResponse response;
        try {
            // 发送请求
            response = client.execute(orderChangeRequest);
        } catch(ApiException apiException) {
            log.info("【{}】同步订单变更数据请求异常，【{}】【{}】【{}】【{}】", KoubeiConsts.CHANNEL_NAME,
                    apiException.getErrCode(), apiException.getErrMsg(),
                    apiException.getSubErrCode(), apiException.getSubErrMsg());
            return;
        }

        log.info("【{}】同步订单变更数据请求发送完成，返回数据【{}】", KoubeiConsts.CHANNEL_NAME, JSON.toJSONString(response));
        if (Objects.isNull(response) || !response.isSuccess()) {

            log.info("【{}】发送同步数据请求失败，【{}】【{}】【{}】【{}】", KoubeiConsts.CHANNEL_NAME,
                    Optional.ofNullable(response).map(res->res.getErrorCode()).orElse(""),
                    Optional.ofNullable(response).map(res->res.getMsg()).orElse(""),
                    Optional.ofNullable(response).map(res->res.getSubCode()).orElse(""),
                    Optional.ofNullable(response).map(res->res.getSubMsg()).orElse(""));
        }

        if (! (response instanceof LifeReservationItemOrderChangeResponse)) {
            log.info("同步请求的返回数据格式不正确");
            return;
        }

        LifeReservationItemOrderChangeResponse orderChangeResponse = (LifeReservationItemOrderChangeResponse)response;
        LifeReservationItemOrderChangeResponse.Result orderChangeResult = orderChangeResponse.getResult();
        if (Objects.nonNull(orderChangeResult) && orderChangeResult.getSuccess()) {
            return;
        }

        log.info(String.format("发送请求返回失败,失败提示消息[{}]",
                Optional.ofNullable(orderChangeResult.getError()).map(tribeError -> tribeError.getMessage()).orElse("")));
    }
}
